home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 11
/
Cream of the Crop 11-1.iso
/
sound
/
simul100.zip
/
SIMUL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-27
|
12KB
|
484 lines
/* █ SIMUL.C ██████████████████████████████████████████████████████████████ */
/* Copyright 1995 by Ethan Brodsky. All right reserved. */
#define TRUE 1
#define FALSE 0
typedef unsigned char BYTE;
int init_sb(int base_io, int irq, int dma_8, int dma_16, int rate);
void shutdown_sb(void);
void set_blocklength(int block_length);
void get_buffers(void);
void free_buffers(void);
void install_handler_8(void (far *handler)());
void install_handler_16(void (far *handler)());
void start_input16(void);
void start_output8(void);
void stop_sound(void);
volatile long intcount;
volatile long intcount_8;
volatile long intcount_16;
volatile int error = FALSE;
int curblock_8;
int curblock_16;
unsigned char far *blockptr_8[2];
unsigned char far *buf_8;
signed short far *blockptr_16[2];
signed short far *buf_16;
/* ████████████████████████████████████████████████████████████████████████ */
#include <alloc.h>
#include <dos.h>
#include <mem.h>
#include <stdio.h>
#include <stdlib.h>
#define hi(x) ((x) >> 8)
#define lo(x) ((x) & 0xFF)
typedef enum {INT8, INT16, ERROR} INTTYPE;
int resetport;
int readport;
int writeport;
int pollport;
int ack8port;
int ack16port;
int mixer_addrport;
int mixer_dataport;
int sampling_rate;
int pic_rotateport;
int pic_maskport;
int irq_startmask;
int irq_stopmask;
int irq_intvector;
int dma8_maskport;
int dma8_clrptrport;
int dma8_modeport;
int dma8_addrport;
int dma8_countport;
int dma8_pageport;
int dma8_startmask;
int dma8_stopmask;
int dma8_mode;
int dma16_maskport;
int dma16_clrptrport;
int dma16_modeport;
int dma16_addrport;
int dma16_countport;
int dma16_pageport;
int dma16_startmask;
int dma16_stopmask;
int dma16_mode;
void far *mem_8 = NULL;
unsigned char far *buf_8 = NULL;
unsigned char far *blockptr_8[2] = {NULL, NULL};
long buffer8_addr;
int buffer8_page;
int buffer8_ofs;
void far *mem_16 = NULL;
signed short far *buf_16 = NULL;
signed short far *blockptr_16[2] = {NULL, NULL};
long buffer16_addr;
int buffer16_page;
int buffer16_ofs;
void (far *handler_8)(void) = NULL;
void (far *handler_16)(void) = NULL;
static void (interrupt far *oldintvector)(void) = NULL;
int inthandler_installed = FALSE;
unsigned int blocklength = 0;
unsigned int bufferlength = 0;
/* ──────────────────────────────────────────────────────────────────────── */
void write_dsp(BYTE value)
{
while ((inp(writeport) & 0x80));
outp(writeport, value);
}
BYTE read_dsp(void)
{
while (!(inp(pollport) & 0x80));
return(inp(readport));
}
void write_mixer(BYTE reg, BYTE value)
{
outp(mixer_addrport, reg);
outp(mixer_dataport, value);
}
BYTE read_mixer(BYTE reg)
{
outp(mixer_addrport, reg);
return inp(mixer_dataport);
}
int reset_dsp(void)
{
int i;
outp(resetport, 1);
delay(1);
outp(resetport, 0);
i = 100;
while ((i-- > 0) && (read_dsp() != 0xAA))
{ }
return(i > 0);
}
void set_rate(int rate)
{
/* Output rate */
write_dsp(0x41);
write_dsp(hi(rate));
write_dsp(lo(rate));
/* Input rate */
write_dsp(0x42);
write_dsp(hi(rate));
write_dsp(lo(rate));
}
/* ════════════════════════════════════════════════════════════════════════ */
void install_inthandler(void);
void uninstall_inthandler(void);
void simul_exitproc(void);
int init_sb(int base_io, int irq, int dma_8, int dma_16, int rate)
{
static int pageport[8] = {0x87, 0x83, 0x81, 0x82, -1, 0x8B, 0x89, 0x8A};
/* Sound card DSP IO ports */
resetport = base_io + 0x006;
readport = base_io + 0x00A;
writeport = base_io + 0x00C;
pollport = base_io + 0x00E;
ack8port = base_io + 0x00E;
ack16port = base_io + 0x00F;
/* Sound card mixer IO ports */
mixer_addrport = base_io + 0x004;
mixer_dataport = base_io + 0x005;
/* Reset DSP */
if (!reset_dsp())
return FALSE;
/* Make sure that sound hardware is SB16 */
write_dsp(0xE1);
if (read_dsp() < 4)
return FALSE;
read_dsp();
/* Calculate interrupt controller ports and parameters */
if (irq < 8)
{ /* PIC1 */
irq_intvector = 0x08 + irq;
pic_rotateport = 0x20;
pic_maskport = 0x21;
}
else
{ /* PIC2 */
irq_intvector = 0x70 + irq-8;
pic_rotateport = 0xA0;
pic_maskport = 0xA1;
}
irq_stopmask = 1 << (irq % 8);
irq_startmask = ~irq_stopmask;
/* Calculate DMA controller ports and parameters */
dma16_maskport = 0xD4;
dma16_clrptrport = 0xD8;
dma16_modeport = 0xD6;
dma16_addrport = 0xC0 + 4*(dma_16-4);
dma16_countport = 0xC2 + 4*(dma_16-4);
dma16_pageport = pageport[dma_16];
dma16_stopmask = 0x04 | (dma_16-4);
dma16_startmask = 0x00 | (dma_16-4);
dma16_mode = 0x54 | (dma_16-4); /* single ++ A/I, write to mem */
dma8_maskport = 0x0A;
dma8_clrptrport = 0x0C;
dma8_modeport = 0x0B;
dma8_addrport = 0x00 + 2*dma_8;
dma8_countport = 0x01 + 2*dma_8;
dma8_pageport = pageport[dma_8];
dma8_stopmask = 0x04 | dma_8;
dma8_startmask = 0x00 | dma_8;
dma8_mode = 0x58 | dma_8; /* single ++ A/I, read from mem */
/* Sampling rate */
sampling_rate = rate;
set_rate(sampling_rate);
install_inthandler();
atexit(simul_exitproc);
return TRUE;
}
/* ──────────────────────────────────────────────────────────────────────── */
void shutdown_sb(void)
{
if (inthandler_installed) uninstall_inthandler();
reset_dsp();
}
/* ════════════════════════════════════════════════════════════════════════ */
void set_blocklength(int block_length)
{
blocklength = block_length;
bufferlength = 2*block_length;
}
/* ════════════════════════════════════════════════════════════════════════ */
long getlinearaddr(void far *ptr)
{
return ((long)FP_SEG(ptr) << 4) + (long)FP_OFF(ptr);
}
void get_buffers(void)
{
/* 8-bit */
buf_8 = mem_8 = malloc(2*bufferlength);
if (mem_8 == NULL)
exit(EXIT_FAILURE);
if (((getlinearaddr(mem_8) % 65536) + bufferlength) > 65536)
buf_8 += 1;
blockptr_8[0] = buf_8;
blockptr_8[1] = buf_8 + blocklength;
buffer8_addr = getlinearaddr(buf_8);
buffer8_page = buffer8_addr / 65536;
buffer8_ofs = buffer8_addr % 65536;
_fmemset(buf_8, 0x80, bufferlength);
/* 16-bit */
buf_16 = mem_16 = malloc(4*bufferlength);
if (mem_16 == NULL)
exit(EXIT_FAILURE);
if ((((getlinearaddr(mem_16) >> 1) % 65536) + bufferlength) > 65536)
buf_16 += 1;
blockptr_16[0] = buf_16;
blockptr_16[1] = buf_16 + blocklength;
buffer16_addr = getlinearaddr(buf_16);
buffer16_page = buffer16_addr / 65536;
buffer16_ofs = (buffer16_addr >> 1) % 65536;
_fmemset(buf_16, 0x00, 2*bufferlength);
curblock_8 = 0;
curblock_16 = 0;
intcount_8 = 0;
intcount_16 = 0;
intcount = 0;
}
/* ──────────────────────────────────────────────────────────────────────── */
void free_buffers(void)
{
#ifdef __SMALL__ || __MEDIUM__
free((void *)mem_8);
free((void *)mem_16);
#else
farfree(mem_8);
farfree(mem_16);
#endif
}
/* ════════════════════════════════════════════════════════════════════════ */
void install_handler_8(void (far *handler)())
{
handler_8 = handler;
}
/* ──────────────────────────────────────────────────────────────────────── */
void install_handler_16(void (far *handler)())
{
handler_16 = handler;
}
/* ════════════════════════════════════════════════════════════════════════ */
void start_input16(void)
{
outp(dma16_maskport, dma16_stopmask);
outp(dma16_clrptrport, 0x00);
outp(dma16_modeport, dma16_mode);
outp(dma16_addrport, lo(buffer16_ofs));
outp(dma16_addrport, hi(buffer16_ofs));
outp(dma16_countport, lo(bufferlength-1));
outp(dma16_countport, hi(bufferlength-1));
outp(dma16_pageport, buffer16_page);
outp(dma16_maskport, dma16_startmask);
write_dsp(0xBE); /* 16-bit cmd - A/D - A/I - FIFO */
write_dsp(0x10); /* 16-bit mode - signed mono */
write_dsp(lo(blocklength-1));
write_dsp(hi(blocklength-1));
}
/* ──────────────────────────────────────────────────────────────────────── */
void start_output8(void)
{
outp(dma8_maskport, dma8_stopmask);
outp(dma8_clrptrport, 0x00);
outp(dma8_modeport, dma8_mode);
outp(dma8_addrport, lo(buffer8_ofs));
outp(dma8_addrport, hi(buffer8_ofs));
outp(dma8_countport, lo(bufferlength-1));
outp(dma8_countport, hi(bufferlength-1));
outp(dma8_pageport, buffer8_page);
outp(dma8_maskport, dma8_startmask);
write_dsp(0x48); /* Set DSP block transfer size */
write_dsp(lo(blocklength-1));
write_dsp(hi(blocklength-1));
write_dsp(0x1C); /* 8-bit auto-init DMA mono output */
}
/* ════════════════════════════════════════════════════════════════════════ */
void stop_sound(void)
{
write_dsp(0xD0); /* Pause 8-bit sound */
write_dsp(0xDA); /* Exit 8-bit A/I sound */
outp(dma8_maskport, dma8_stopmask); /* Mask DMA channel */
write_dsp(0xD5); /* Pause 16-bit sound */
write_dsp(0xD9); /* Exit 16-bit A/I sound */
outp(dma16_maskport, dma16_stopmask); /* Mask 16-gbit DMA channel */
}
/* ════════════════════════════════════════════════════════════════════════ */
INTTYPE inttype(void)
{
BYTE intstatus;
/* Read Interrupt Status Register */
intstatus = read_mixer(0x82);
if ((intstatus & 0x01) && (intstatus & 0x02))
return ERROR;
if (intstatus & 0x01)
return INT8;
if (intstatus & 0x02)
return INT16;
return ERROR;
}
void toggleblock(int *blocknum)
{
*blocknum = !(*blocknum);
}
void interrupt inthandler(void)
{
intcount++;
switch(inttype())
{
/* 8-bit sound */
case INT8:
intcount_8++;
if (handler_8 != NULL) handler_8();
toggleblock(&curblock_8);
inp(ack8port);
break;
/* 16-bit sound */
case INT16:
intcount_16++;
if (handler_16 != NULL) handler_16();
toggleblock(&curblock_16);
inp(ack16port);
break;
/* Problem */
case ERROR:
error = TRUE;
break;
}
outp(0xA0, 0x20); /* Acknowledge EOI with PIC2 */
outp(0x20, 0x20); /* Acknowledge EOI with PIC1 */
}
void install_inthandler(void)
{
disable();
outp(pic_maskport, (inp(pic_maskport) | irq_stopmask));
oldintvector = _dos_getvect(irq_intvector);
_dos_setvect(irq_intvector, inthandler);
outp(pic_maskport, (inp(pic_maskport) & irq_startmask));
enable();
inthandler_installed = TRUE;
}
void uninstall_inthandler(void)
{
disable();
outp(pic_maskport, (inp(pic_maskport) | irq_stopmask));
_dos_setvect(irq_intvector, oldintvector);
enable();
inthandler_installed = FALSE;
}
void simul_exitproc(void)
{
stop_sound();
shutdown_sb();
}
/* ████████████████████████████████████████████████████████████████████████ */